package com.gitee.wsl.base

import com.gitee.wsl.ext.number.toString

/** Common value ranges, such as [ValueRange.Normalized]. */
sealed class ValueRange<T : Comparable<T>>(
    override  val start: T,
    override  val endInclusive: T,
) : ClosedRange<T> {
    /** Synonym for [start] */
      val min: T get() = start

    /** Synonym for [endInclusive] */
      val max: T get() = endInclusive

    /** Returns the string representation of the specified value. */
    protected abstract fun formatValue(value: T): String

    override fun toString(): String = "${formatValue(start)}..${formatValue(endInclusive)}"

    /** Values with allowed values `0.0..1.0` */
    object Normalized : ValueRange<Double>(0.0, 1.0) {
        override fun formatValue(value: Double): String = value.toString(1)
    }

    /** Values with allowed values `0..255` */
    object Bytes : ValueRange<Int>(0, 255) {
        override fun formatValue(value: Int): String = value.toString(16).padStart(2, '0')
    }

    /** Values with allowed values `0.0..360.0`° */
    object Angle : ValueRange<Double>(0.0, 360.0) {
        override fun formatValue(value: Double): String = "${value.toString(1)}°"
    }

    /** Values with allowed values `0.0..100.0`% */
     object Percent : ValueRange<Double>(0.0, 100.0) {
        override fun formatValue(value: Double): String = "${value.toString(1)}%"
    }

    /** Values with allowed values `-1.0..+1.0` */
     object Scaling : ValueRange<Double>(-1.0, +1.0) {
        /** Value that signifies no scaling */
         const val None: Double = 0.0
        override fun formatValue(value: Double): String = when {
            value > None -> "+${value.toString(1)}"
            else -> value.toString(1)
        }
    }
}